/*
 * Copyright 2022. Huawei Technologies Co., Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.huawei.jenkins.plugins.storage;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractProject;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import hudson.util.FormValidation;
import jenkins.tasks.SimpleBuildStep;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;

import javax.annotation.Nonnull;
import java.io.IOException;

/**
 * maven项目构建后目标文件上传
 */
public class OBSClassicUpload extends Recorder implements SimpleBuildStep {
    private String ak;

    private String sk;

    private String bucket;

    private String endpoint;

    // 本地文件路径
    private String file;

    // 桶上文件路径
    private String path;

    // kms加密密钥id
    private String kmsId;

    // 包含文件正则路径
    private String includePathPattern;

    // 排除文件正则路径
    private String excludePathPattern;

    // 本地文件根目录
    private String workingDir;

    // 用户自定义标签，暂未使用
    private String[] metadatas;

    // 访问权限设置
    private String acl;

    // 指定对象被下载时的网页的缓存格式
    private String cacheControl;

    // 缓存过期时间
    private String expires;

    // 指定对象被下载时的内容编码格式
    private String contentEncoding;

    // 设置对象的文件类型
    private String contentType;

    // 提供一个默认的文件名赋值给该对象
    private String contentDisposition;

    // 重定向
    private String redirectLocation;

    public String getAk() {
        return ak;
    }

    @DataBoundSetter
    public void setAk(String ak) {
        this.ak = ak;
    }

    public String getSk() {
        return sk;
    }

    @DataBoundSetter
    public void setSk(String sk) {
        this.sk = sk;
    }

    public String getBucket() {
        return bucket;
    }

    @DataBoundSetter
    public void setBucket(String bucket) {
        this.bucket = bucket;
    }

    public String getEndpoint() {
        return endpoint;
    }

    @DataBoundSetter
    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }

    public String getFile() {
        return file;
    }

    @DataBoundSetter
    public void setFile(String file) {
        this.file = file;
    }

    public String getPath() {
        return path;
    }

    @DataBoundSetter
    public void setPath(String path){
        this.path = path;
    }

    public String getKmsId() {
        return kmsId;
    }

    @DataBoundSetter
    public void setKmsId(String kmsId) {
        this.kmsId = kmsId;
    }

    public String getIncludePathPattern() {
        return StringUtils.isBlank(includePathPattern) ? null : includePathPattern;
    }

    @DataBoundSetter
    public void setIncludePathPattern(String includePathPattern) {
        this.includePathPattern = includePathPattern;
    }

    public String getExcludePathPattern() {
        return StringUtils.isBlank(excludePathPattern) ? null : excludePathPattern;
    }

    @DataBoundSetter
    public void setExcludePathPattern(String excludePathPattern) {
        this.excludePathPattern = excludePathPattern;
    }

    public String getWorkingDir() {
        return workingDir;
    }

    @DataBoundSetter
    public void setWorkingDir(String workingDir) {
        this.workingDir = workingDir;
    }

    public String[] getMetadatas() {
        return metadatas;
    }

    @DataBoundSetter
    public void setMetadatas(String[] metadatas) {
        this.metadatas = metadatas;
    }

    public String getAcl() {
        return acl;
    }

    @DataBoundSetter
    public void setAcl(String acl) {
        this.acl = acl;
    }

    public String getCacheControl() {
        return cacheControl;
    }

    @DataBoundSetter
    public void setCacheControl(String cacheControl) {
        this.cacheControl = cacheControl;
    }

    public String getExpires() {
        return expires;
    }

    @DataBoundSetter
    public void setExpires(String expires) {
        this.expires = expires;
    }

    public String getContentEncoding() {
        return contentEncoding;
    }

    @DataBoundSetter
    public void setContentEncoding(String contentEncoding) {
        this.contentEncoding = contentEncoding;
    }

    public String getContentType() {
        return contentType;
    }

    @DataBoundSetter
    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public String getContentDisposition() {
        return contentDisposition;
    }

    @DataBoundSetter
    public void setContentDisposition(String contentDisposition) {
        this.contentDisposition = contentDisposition;
    }

    public String getRedirectLocation() {
        return redirectLocation;
    }

    @DataBoundSetter
    public void setRedirectLocation(String redirectLocation) {
        this.redirectLocation = redirectLocation;
    }

    @DataBoundConstructor
    public OBSClassicUpload(String ak, String sk, String bucket, String endpoint) {
        // 本类中属性不可删除，jenkins自身机制需要类中属性支持
        this.ak = ak;
        this.sk = sk;
        this.bucket = bucket;
        this.endpoint = endpoint;

    }

    @Override
    public BuildStepMonitor getRequiredMonitorService() {
        return BuildStepMonitor.NONE;
    }

    @Override
    public void perform(@NonNull Run<?, ?> run, @NonNull FilePath workspace, @NonNull EnvVars env, @NonNull Launcher launcher,
                        @NonNull TaskListener listener) throws InterruptedException, IOException {
        CustomInput customInput = new CustomInput();
        customInput.setAk(ak);
        customInput.setSk(sk);
        customInput.setBucket(bucket);
        customInput.setEndpoint(endpoint);
        customInput.setFile(file);
        customInput.setPath(path);
        customInput.setKmsId(kmsId);
        customInput.setIncludePathPattern(includePathPattern);
        customInput.setExcludePathPattern(excludePathPattern);
        customInput.setWorkingDir(workingDir);
        customInput.setMetadatas(metadatas);
        customInput.setAcl(acl);
        customInput.setCacheControl(cacheControl);
        customInput.setExpires(expires);
        customInput.setContentEncoding(contentEncoding);
        customInput.setContentType(contentType);
        customInput.setContentDisposition(contentDisposition);
        customInput.setRedirectLocation(redirectLocation);
        ObsService.upload(env, workspace, listener, customInput);
    }

    @Symbol("OBSClassicUpload")
    @Extension
    public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {

        public FormValidation doCheckAk(@QueryParameter(required = true) String value) {
            return checkValue(value, Messages.OBSPublish_MissingAccessKey());
        }

        public FormValidation doCheckSk(@QueryParameter(required = true) String value) {
            return checkValue(value, Messages.OBSPublish_MissingSecretKey());
        }
        public FormValidation doCheckBucket(@QueryParameter(required = true) String value) {
            return checkValue(value, Messages.OBSPublish_MissingBucket());
        }

        public FormValidation doCheckEndpoint(@QueryParameter(required = true) String value) {
            return checkValue(value, Messages.OBSPublish_MissingEndpoint());
        }

        public FormValidation doCheckPath(@QueryParameter(required = true) String value) {
            return checkValue(value, Messages.OBSPublish_MissingPath());
        }

        private FormValidation checkValue(String value, String message) {
            if (StringUtils.isBlank(value)) {
                return FormValidation.error(message);
            }
            return FormValidation.ok();
        }

        @Override
        public boolean isApplicable(Class<? extends AbstractProject> jobType) {
            return true;
        }

        @Nonnull
        @Override
        public String getDisplayName() {
            return Messages.OBSPublish_DisplayName();
        }
    }

}
